package com.example.testluckyroulette.widget

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.*
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.annotation.RequiresApi
import com.example.testluckyroulette.R
import com.example.testluckyroulette.bean.LuckyPersonBean
import kotlin.math.cos
import kotlin.math.sin


/**
 * Create Time:2020/9/7
 * Author: Lindanrong
 * Description:一个幸运的轮盘
 * 本控件的责任 ： 根据传递进来的个数 计算每个项占有的角度。
 *                并进行画图使用
 */
class LuckyRoulettes1View : View {

    companion object {
        private const val TAG = "LuckyRouletteView"
    }

    var mBackRoundPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) //背景圆盘
    var mRadio: Int = 0 //圆盘的半径
    var mRect: RectF = RectF()//圆盘的矩形
    var mTextStrRectF = RectF() //构建文字圆盘的矩形
    var mImageRectF = RectF() //构建头像的矩形

    var mHeight: Int = 0 //记录本控件的高
    var mWith: Int = 0 //记录本控件的宽
    var bitmap: Bitmap? = null // bitmap
    var mContext: Context
    private var objectAnimator: ObjectAnimator? = null
    lateinit var mPersonBeanList: MutableList<LuckyPersonBean>
    var textX = 0f
    var textY = 0f

    var mSumAlllist = 0 //总数传入进来的数据的总数
    private var mRepeatCount = 6 //转几圈
    private var mStartAngle = 0f //存储圆盘开始的位置
    private var mItemAngle = 0f//每个item的角度
    private val mPaintItemStr = Paint(Paint.ANTI_ALIAS_FLAG) //转盘文字画笔

    lateinit var luckyPerson: LuckyPersonBean
    val mPath = Path() //文字的路径
    val mImagePath = Path()//头像的path

    lateinit var bitMapShader:BitmapShader //圆头像的画笔头
     var bitMapPaint:Paint = Paint() //圆头像的画笔

    init {
        //背景
        mBackRoundPaint.style = Paint.Style.FILL
        bitMapPaint.style = Paint.Style.FILL
        mPaintItemStr.color = Color.parseColor("#ED2F2F")
        mPaintItemStr.strokeWidth = 3f
        mPaintItemStr.textAlign = Paint.Align.CENTER
        mPaintItemStr.textSize = 50f


    }

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)

    constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attributeSet,
        defStyleAttr
    ) {
        mContext = context
        bitmap = BitmapFactory.decodeResource(mContext.resources, R.mipmap.ic_luckdrawstart) //中心的图像
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        Log.d(
            TAG,
            "onMeasure: 宽：${MeasureSpec.getSize(widthMeasureSpec)},高：${MeasureSpec.getSize(
                heightMeasureSpec
            )}"
        )
        mHeight = MeasureSpec.getSize(heightMeasureSpec)
        mWith = MeasureSpec.getSize(widthMeasureSpec)
        mRadio = mWith.coerceAtMost(mHeight) / 2  //求出两个值哪个比较小
        //确定一下圆心的坐标
        mRect.run {
            top = 0f
            left = 0f
            right = mRadio * 2f
            bottom = mRadio * 2f
        }
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

    }

    /**
     * 计算头像的矩阵 跟 字体的矩阵
     */
    private fun calculateImageAndTextRectF() {
        //名字矩阵位置 用于画弧度的 名字的矩阵位置距离圆心4/10的地方
        mTextStrRectF.run {
            top = 0f + mRadio * 2 / 3
            left = 0f + mRadio * 2 / 3
            right = mRadio * 2f - mRadio * 2 / 3
            bottom = mRadio * 2f - mRadio * 2 / 3
        }
        //名字的矩阵位置距离圆心4/10的地方  用于不画弧度的
        textX = mRadio.toFloat()
        textY = mRadio * 6 / 10f   //6/10是屏幕距离文字的地方
        var b =  bottomLength31(mItemAngle/2,mRadio.toFloat())
        //头像矩阵位置
        mImageRectF.run {
            top = mRadio * 1 /3 - 100f
            left = mRadio - 100f
            right = mRadio + 100f
            bottom = mRadio * 1 /3 + 100f
        }

    }

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        //这里第三个参数 是指要滑动的角度
//        calculateAllAngelAndDraw(canvas)
//        testCalculateAllAngelAndDraw(canvas)
        drawTextAndCircleImage(canvas)
    }

    /**
     * 传入要滚动的item 并设置中奖的item
     */
    fun setData(personBeanList: MutableList<LuckyPersonBean>, personBean: LuckyPersonBean) {
        mPersonBeanList = personBeanList
        //获取item的总数
        mSumAlllist = mPersonBeanList.size
        //计算每个item的角度
        mItemAngle = 360f / mSumAlllist
        //记录每个item的中心角度
        for (index in 0 until mSumAlllist) {
            mPersonBeanList[index].mCenterAngle =
                mStartAngle + mItemAngle * index + mItemAngle / 2
        }
        luckyPerson = personBean
        calculateImageAndTextRectF()
        invalidate()
    }

    /**
     * 画出字体(字体是根据路径来绘画的)跟头像
     */
    private fun calculateAllAngelAndDraw(canvas: Canvas) {
        //这里的三个参数  旋转的角度  选中的圆心的 x 跟 y
        // 先旋转 后作画图 （作画后再旋转就没用了）
        canvas.rotate(-90f, mRadio.toFloat(), mRadio.toFloat())
        for (index in 0 until mSumAlllist) {
            //设置画笔颜色
            mBackRoundPaint.color = mContext.resources.getColor(mPersonBeanList[index].color)
            //画弧度圆
            canvas.drawArc(
                mRect,
                mStartAngle + mItemAngle * index,
                mItemAngle,
                true,
                mBackRoundPaint
            )

            //根据路径画字体
            mPath.reset()//将之前的清空 再写入新的路径去绘画文字
            mPath.addArc(mTextStrRectF, mStartAngle + mItemAngle * index, mItemAngle) //文字的路径圆形比盘的小
            canvas.drawTextOnPath(mPersonBeanList[index].name, mPath, 0f, 0f, mPaintItemStr)

            //画头像
            canvas.save() //save()跟restore()要成对存在 -- 表示在save到restore中的旋转放大缩小等 只对这两方法间的绘画起作用
            canvas.rotate(90f, mRadio.toFloat(), mRadio.toFloat()) //将原来的画布-90旋转回来90回来
            canvas.rotate(
                mPersonBeanList[index].mCenterAngle,
                mRadio.toFloat(),
                mRadio.toFloat()
            )// 再进行item中心角度的旋转，并画头像
            canvas.drawBitmap(bitmap!!, null, mImageRectF, mBackRoundPaint)
            canvas.restore()
        }
    }
    /**
     * 画出字体(字体是直接在绘画的然后旋转一下)跟头像
     */
    private fun testCalculateAllAngelAndDraw(canvas: Canvas) {
        //这里的三个参数  旋转的角度  选中的圆心的 x 跟 y
        // 先旋转 后作画图 （作画后再旋转就没用了）
        canvas.rotate(-90f, mRadio.toFloat(), mRadio.toFloat())
        for (index in 0 until mSumAlllist) {
            //设置画笔颜色
            mBackRoundPaint.color = mContext.resources.getColor(mPersonBeanList[index].color)
            //画弧度圆
            canvas.drawArc(
                mRect,
                mStartAngle + mItemAngle * index,
                mItemAngle,
                true,
                mBackRoundPaint
            )
            //画头像
            canvas.save() //save()跟restore()要成对存在 -- 表示在save到restore中的旋转放大缩小等 只对这两方法间的绘画起作用
            canvas.rotate(90f, mRadio.toFloat(), mRadio.toFloat()) //将原来的画布-90旋转回来90回来
            canvas.rotate(
                mPersonBeanList[index].mCenterAngle,
                mRadio.toFloat(),
                mRadio.toFloat()
            )// 再进行item中心角度的旋转，并画头像
            canvas.drawBitmap(mPersonBeanList[index].avatarBitmap!!, null, mImageRectF, mBackRoundPaint)
//            canvas.drawBitmap(bitmap!!, null, mImageRectF, mBackRoundPaint)
            //画字体 求出位置然后画字体
            canvas.drawText(mPersonBeanList[index].name, textX, textY, mPaintItemStr)

            canvas.restore()
        }
    }
    /**
     * 画出字体(字体是直接在绘画的然后旋转一下)跟圆形头像等
     */
    @RequiresApi(Build.VERSION_CODES.KITKAT)
    private fun drawTextAndCircleImage(canvas: Canvas) {
        //这里的三个参数  旋转的角度  选中的圆心的 x 跟 y
        // 先旋转 后作画图 （作画后再旋转就没用了）
        canvas.rotate(-90f, mRadio.toFloat(), mRadio.toFloat())
        for (index in 0 until mSumAlllist) {
            //设置画笔颜色
            mBackRoundPaint.color = mContext.resources.getColor(mPersonBeanList[index].color)
            //画弧度圆
            canvas.drawArc(
                mRect,
                mStartAngle + mItemAngle * index,
                mItemAngle,
                true,
                mBackRoundPaint
            )
            //画头像
            canvas.save() //save()跟restore()要成对存在 -- 表示在save到restore中的旋转放大缩小等 只对这两方法间的绘画起作用
            canvas.rotate(90f, mRadio.toFloat(), mRadio.toFloat()) //将原来的画布-90旋转回来90回来
            // 再进行item中心角度的旋转
            canvas.rotate(
                mPersonBeanList[index].mCenterAngle,
                mRadio.toFloat(),
                mRadio.toFloat()
            )
            //画头像
            var x = (mRadio/4f)/mPersonBeanList[index].avatarBitmap.width
            var y =  (mRadio/4f)/mPersonBeanList[index].avatarBitmap.height
            bitMapShader = BitmapShader(mPersonBeanList[index].avatarBitmap,Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
            bitMapPaint.shader = bitMapShader

            canvas.drawCircle(mImageRectF.centerX(),mImageRectF.centerY(),mRadio/4f,bitMapPaint)
            canvas.drawRect(mImageRectF,bitMapPaint)
            //画字体 求出位置然后画字体
            canvas.drawText(mPersonBeanList[index].name, textX, textY, mPaintItemStr)

            canvas.restore()
        }
    }

    /**
     * 开始动画
     * 转动几圈 + 要被转动到的位置  （正向转动）   这个地方主要是安卓转动的方向是反方向转动 比如转30° 相当于你正方向转 360-30 才能让不动的指针指到同一位置
     * mStartAngle + mRepeatCount * 360 + (360 - luckyPerson.centerAngle.toInt())
     * mStartAngle - mRepeatCount * 360  - luckyPerson.angle.toInt()//转动几圈 + 要被转动到的位置 （反向向转动）
     */
    fun startAnimal() {
        objectAnimator?.cancel()
        objectAnimator = ObjectAnimator.ofFloat(
            this,
            "rotation",
            mStartAngle,
            mStartAngle + mRepeatCount * 360 + (360 - luckyPerson.mCenterAngle.toInt())
        ).apply {
            interpolator = AccelerateDecelerateInterpolator()
            duration = 5000
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    super.onAnimationEnd(animation)
                    Log.d(
                        TAG,
                        "onAnimationEnd: ${luckyPerson.mCenterAngle}+${luckyPerson.name}"
                    )
                }
            })
            start()
        }
    }

    /**
     * 修改bitmap的大小比例
     * @param bitmap 原始Bitmap
     * @param newWidth 新的宽度
     * @param newHeight 新的高度
     */
    private fun changeBitmapSize(bitmap:Bitmap,newWidth:Int,newHeight:Int): Bitmap? {
        val width = bitmap.width
        val height = bitmap.height
        Log.e("width", "width:$width")
        Log.e("height", "height:$height")
        //设置想要的大小
//        val newWidth = 30
//        val newHeight = 30

        //计算压缩的比率
        val scaleWidth = newWidth.toFloat() / width
        val  dx = (newWidth.toFloat() - width * scaleWidth) * 0.5f
        val scaleHeight = newHeight.toFloat() / height
        val dy =  (newHeight.toFloat() - width * scaleHeight) * 0.5f
        //获取想要缩放的matrix
        val matrix = Matrix()
        matrix.setScale(scaleWidth, scaleHeight)
        matrix.setTranslate(dx,dy)
        //获取新的bitmap
        var newbitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)
        newbitmap.width
        newbitmap.height
        Log.e("newWidth", "newWidth" + newbitmap.width)
        Log.e("newHeight", "newHeight" + newbitmap.height)
        return newbitmap
    }


    /*****
     * 以下是用于辅助计算的方法
     *
     *                                                        *
     *                                                       **
     *                                                      * |*
     *                                                     *  | *
     *                                                    *   |  *
     *                                                   *    |   *
     *                                                  * ----|----*          1/3    横切的长度
     *                                                 *      |     *
     *                                                *  -----|----  *           中线的横切的长度
     *                                               *        |       *
     *                                              * --------|------- *        2/3    横切的长度
     *                                             *          |         *
     *                                            * *********************       底部的横线长度
     *                                                     中间这条是高
     *
     */

    /**
     * 获取中间的高的长度
     */
    fun getCenterHeight(centerAngle: Float, radio: Float): Float {
        return cos(centerAngle) * radio
    }

    /**
     * 获取弧度的底部的横线长度
     * @param centerAngle item的一半角度
     * @param radio 半径
     */
    fun bottomLength(centerAngle: Float, radio: Float): Float {
        return 2 * radio / sin(centerAngle.toDouble()).toFloat()
    }

    /**
     * 获取弧度的中线的横切的长度
     */
    fun bottomLength21(centerAngle: Float, radio: Float): Float {
        return bottomLength(centerAngle, radio) / 2
    }

    /**
     * 获取弧度的中线的横切的长度
     */
    fun bottomLength31(centerAngle: Float, radio: Float): Float {
        return bottomLength(centerAngle, radio) / 3
    }

    /**
     * 获取弧度的3分之2中线的横切的长度
     */
    fun bottomLength32(centerAngle: Float, radio: Float): Float {
        return bottomLength(centerAngle, radio) / 3 * 2
    }


}


